#!/usr/bin/env node
/*
 * Copyright (C) 2011-2020 Intel Corporation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *   * Neither the name of Intel Corporation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

import Config from 'config';
import morgan from 'morgan';
import express from 'express';
import logger from './utils/Logger.js';
import node_schedule from 'node-schedule';
import body_parser from 'body-parser';
import routes from './routes/index.js';
import * as fs from 'fs';
import * as https from 'https';
import * as auth from './middleware/auth.js';
import * as error from './middleware/error.js';
import * as refreshService from './services/refreshService.js';
import * as appUtil from './utils/apputil.js';

// Create ./logs if it doesn't exist
fs.mkdir('./logs', (err) => {
  /* do nothing*/
});

const app = express();
const { urlencoded, json } = body_parser;
const { scheduleJob } = node_schedule;

// logger
app.use(morgan('combined', { stream: logger.stream }));

// startup check
if (!appUtil.startup_check()){
  logger.endAndExitProcess();
}

appUtil.database_check().then((db_init_ok) => {
  if (!db_init_ok) {
    logger.endAndExitProcess();
  }

  // body parser middleware, this will let us get the data from a POST
  app.use(urlencoded({ extended: true }));
  app.use(json({ limit: '200000kb' }));

  // authentication middleware
  app.get('/sgx/certification/v3/platforms', auth.validateAdmin);
  app.post('/sgx/certification/v3/platforms', auth.validateUser);
  app.use('/sgx/certification/v3/platformcollateral', auth.validateAdmin);
  app.use('/sgx/certification/v3/refresh', auth.validateAdmin);

  // router
  app.use('/sgx/certification/v3', routes);

  // error handling middleware
  app.use(error.errorHandling);

  // Start HTTPS server
  let privateKey;
  let certificate;
  try {
    privateKey = fs.readFileSync('./ssl_key/private.pem', 'utf8');
    certificate = fs.readFileSync('./ssl_key/file.crt', 'utf8');
  } catch (err) {
    logger.error('The private key or certificate for HTTPS server is missing.');
  }
  const credentials = { key: privateKey, cert: certificate };
  const httpsServer = https.createServer(credentials, app);
  httpsServer.listen(
    Config.get('HTTPS_PORT'),
    Config.get('hosts'),
    function () {
      logger.info(
        'HTTPS Server is running on: https://localhost:' +
          Config.get('HTTPS_PORT')
      );
    }
  );

  // Schedule the refresh job in cron-style
  // # ┌───────────── minute (0 - 59)
  // # │ ┌───────────── hour (0 - 23)
  // # │ │ ┌───────────── day of the month (1 - 31)
  // # │ │ │ ┌───────────── month (1 - 12)
  // # │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
  // # │ │ │ │ │                                   7 is also Sunday on some systems)
  // # │ │ │ │ │
  // # │ │ │ │ │
  // # * * * * * command to execute
  //
  scheduleJob(Config.get('RefreshSchedule'), refreshService.scheduledRefresh);
});

export default app;
